package com.hup.restTimer.view.main;

import com.hup.restTimer.model.AppConfig;
import com.hup.utils.commons.DateBuilder;
import com.hup.utils.swing.ColorUtil;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import javax.swing.JComponent;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.font.GlyphVector;

/**
 * [提醒文本]控件
 *
 * @author hugan
 * @date 2022/10/1
 */
@Slf4j
public class TipsLabel extends JComponent {

    private final AppConfig config;

    @Getter
    private Font font;
    /**
     * 文本颜色
     */
    private Color color;
    /**
     * 文本描边颜色
     */
    private Color colorBorder;

    /**
     * 当前的文本
     */
    private String text;
    private Shape textShape;
    private Rectangle textBounds;

    public TipsLabel(AppConfig config) {
        this.config = config;
        font = new Font(config.tipsFont, Font.BOLD, config.tipsFontSize);
        setColor(config.tipsColor);
    }

    public void setColor(Integer color) {
        this.color = new Color(color, true);
        colorBorder = ColorUtil.reverse(this.color);
        repaint();
    }

    private void updateTextShape() {
        //log.info("");
        if (config.tipsOutline) {
            //构造文本绘制数据,基本不耗时(0ms)
            GlyphVector v = font.createGlyphVector(getFontMetrics(font).getFontRenderContext(), text);
            textShape = v.getOutline();
            textBounds = textShape.getBounds();
        } else {
            FontMetrics metrics = getFontMetrics(font);
            int width = metrics.stringWidth(text);
            int height = metrics.getHeight();
            //此处的 textBounds.y, 是为了与 tipsOutline时的算法一致, 未深究数学算法
            textBounds = new Rectangle(0, -metrics.getAscent(), width, height);
        }
        repaint();
    }

    @Override
    public void setFont(Font font) {
        this.font = font;
        if (config == null) return;//super()时为空
        updateTextShape();
    }

    public void updateTimeStr() {
        if (!config.isResting) {
            long sitTime = System.currentTimeMillis() - config.restTimeLastEd;
            if (sitTime < 1000) sitTime = 0;
            String timeStr = DateBuilder.spanChar(sitTime);
            text = config.tipsTemplate.replace("#", timeStr);
        } else {
            long restTime = System.currentTimeMillis() - config.restTimeSt;
            if (restTime < 1000) restTime = 0;
            String timeStr = DateBuilder.spanChar(restTime);
            text = config.tipsTemplateRest.replace("#", timeStr);
        }
        updateTextShape();
    }

    @Override
    protected void paintComponent(Graphics g0) {
        //log.info("");
        if (textBounds == null) return;//没设置/更新文本

        /*
        绘制带描边的文本
        资料:描边和居中
            https://www.136.la/java/show-3575.html
            不太理解 textBounds 的"x,y取值"和计算方式,纯粹搬代码
         */
        int gravity = config.tipsGravity;
        int x = -textBounds.x + config.tipsMargin;//靠左
        if (gravity == 2 || gravity == 5 || gravity == 8) {//居中
            x = (getWidth() - textBounds.width) / 2 - textBounds.x;
        } else if (gravity == 3 || gravity == 6 || gravity == 9) { //靠右
            x = getWidth() - textBounds.width - textBounds.x - config.tipsMargin;
        }
        int y;
        if (gravity <= 3) { //顶部
            y = -textBounds.y + config.tipsMargin;
        } else if (gravity <= 6) {//居中
            y = (getHeight() - textBounds.height) / 2 - textBounds.y;
        } else {//底部
            y = getHeight() - textBounds.height - textBounds.y - config.tipsMargin;
        }

        Graphics2D g = (Graphics2D) g0;
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);//抗锯齿
        if (config.tipsOutline) {
            g.translate(x, y);
            //文本
            g.setColor(color);
            g.fill(textShape);
            //描边
            g.setColor(colorBorder);
            g.setStroke(new BasicStroke(2));
            g.draw(textShape);
        } else {
            g.setColor(color);
            g.drawString(text, x, y);
        }
    }

}
